﻿using System;
using System.Collections.Generic;
using System.Linq;
using MIAP.DataAccess.Interfaces;
using MIAP.DataAccess.SqlServer.Model;
using MIAP.Entidades;

namespace MIAP.DataAccess.Implementaciones.SQL
{
    /// <summary>
    /// Clase de las operaciones de acceso a datos para el módulo de perfieles usuario.
    /// </summary>
    public class UsuarioPerfilDao : IUsuarioPerfilDao
    {
        #region Operaciones relacionadas a la vista AdministraPerfilesUsuario

        /// <summary>
        /// Obtiene todos los perfiles de un determinado usuario.
        /// </summary>
        /// <param name="idUsuario">Usuario del cual serán obtenidos los perfiles.</param>
        /// <returns>Lista con los perfiles del usuario.</returns>
        public IList<PerfilInfo> GetPerfilesByUsuario(int idUsuario)
        {
            IList<PerfilInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = (from perfilesUsuario in context.MIAP_USUARIO_PERFIL
                             join perfil in context.MIAP_PERFIL
                             on perfilesUsuario.ID_PERFIL equals perfil.ID_PERFIL
                             join proyecto in context.MIAP_PROYECTO
                             on perfil.ID_PROYECTO equals proyecto.ID_PROYECTO into proyectoPerfil
                             where perfilesUsuario.ID_USUARIO == idUsuario
                             from perfilProyecto in proyectoPerfil.DefaultIfEmpty()
                             select new PerfilInfo
                             {
                                 IdPerfil = perfilesUsuario.ID_PERFIL,
                                 NombrePerfil = perfil.NOMBRE,

                                 Proyecto = new ProyectoInfo()
                                 {
                                     NombreProyecto = perfilProyecto.NOMBRE
                                 }

                             });

                result = query.ToList();
            }

            return result;
        }

        /// <summary>
        /// Elimina un perfil relacionado con un usuario.
        /// </summary>
        /// <param name="idUsuario">Es el id del usuario al que se le eliminará el perfil.</param>
        /// <param name="idPerfil">Es el id del perfil que será eliminado.</param>
        public void RemovePerfilesByUsuario(int idUsuario, int idPerfil)
        {
            using (var context = new MIAPDBEntities())
            {
                var miapUsuarioPerfil = (from usuarioPerfil in context.MIAP_USUARIO_PERFIL
                                         where usuarioPerfil.ID_USUARIO == idUsuario && usuarioPerfil.ID_PERFIL == idPerfil
                                         select usuarioPerfil).Single();

                context.MIAP_USUARIO_PERFIL.Remove(miapUsuarioPerfil);

                context.SaveChanges();
            }
        }

        #endregion

        #region Operaciones relacionadas a la vista AltaPerfilesUsuario

        /// <summary>
        /// Obtiene todos los archivos relacionados con un proyecto.
        /// </summary>
        /// <param name="idProyecto">Es el id del proyecto para el cual estarán ralacionados los archivos.</param>
        /// <returns>Lista con los archivos relacionados al proyecto.</returns>
        public IList<ArchivoInfo> GetArchivosByIdProyecto(int idProyecto)
        {
            List<ArchivoInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = (from archivo in context.MIAP_ARCHIVO
                            join proyecto in context.MIAP_PROYECTO
                            on archivo.ID_PROYECTO equals proyecto.ID_PROYECTO
                            where archivo.ID_PROYECTO == idProyecto && archivo.ACTIVO == true
                            select new ArchivoInfo
                            {
                                IdentificadorArchivo = archivo.ID_ARCHIVO,
                                NombreArchivo = archivo.NOMBRE,

                                Proyecto = new ProyectoInfo
                                {
                                    IDProyecto = proyecto.ID_PROYECTO,
                                    NombreProyecto = proyecto.NOMBRE
                                }
                            }).Distinct();

                result = query.ToList();
            }

            return result;
        }

        /// <summary>
        /// Agrega un nuevo perfil de usuario.
        /// </summary>
        /// <param name="usuario">Usuario que será agregado.</param>
        /// <param name="listArchivos">Lista de archivos sobre los cuales el usuario tendra </param>
        /// <param name="user">Usuario que ejecuta la operación.</param>
        public void AddPerfilUsuario(UsuarioInfo usuario, List<ArchivoInfo> listArchivos, string user)
        {
            using (var context = new MIAPDBEntities())
            {
                MIAP_USUARIO_PERFIL miapUsuarioPerfil = new MIAP_USUARIO_PERFIL()
                {
                    ID_USUARIO = usuario.IdUsuario,
                    ID_PERFIL = usuario.IdPerfil,
                    PUEDE_EJECUTAR_PROYECTO = usuario.PuedeEjecutarProyecto,
                    USUARIO_CREACION = user,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now,
                    FECHA_CREACION = DateTime.Now
                };

                context.MIAP_USUARIO_PERFIL.Add(miapUsuarioPerfil);

                MIAP_USUARIO_ARCHIVO miapUsuarioArchivo;

                foreach (ArchivoInfo archivo in listArchivos)
                {
                    var usuarioArchivoBD = (from usuarioArchivo in context.MIAP_USUARIO_ARCHIVO
                                           where usuarioArchivo.ID_USUARIO == usuario.IdUsuario && usuarioArchivo.ID_ARCHIVO == archivo.IdentificadorArchivo
                                           select usuarioArchivo).SingleOrDefault();

                    if (usuarioArchivoBD != null)
                    {
                        context.MIAP_USUARIO_ARCHIVO.Remove(usuarioArchivoBD);
                    }

                    miapUsuarioArchivo = new MIAP_USUARIO_ARCHIVO()
                    {
                        ID_USUARIO = usuario.IdUsuario,
                        ID_ARCHIVO = archivo.IdentificadorArchivo,
                        ES_CARGA = archivo.PuedeCargarArchivo,
                        ES_AUTORIZACION = archivo.PuedeAutorizarRecarga,
                        USUARIO_CREACION = user,
                        USUARIO_ACTUALIZACION = user,
                        FECHA_CREACION = DateTime.Now,
                        FECHA_ACTUALIZACION = DateTime.Now

                    };

                    context.MIAP_USUARIO_ARCHIVO.Add(miapUsuarioArchivo);
                }

                context.SaveChanges();
            }
        }

        /// <summary>
        /// Modifica la información del perfil del usuario.
        /// </summary>
        /// <param name="usuario">Usuario que será modificado.</param>
        /// <param name="listArchivos">Lista de archivos relacionados al usuario.</param>
        /// <param name="user">Usuario que ejecuta la operación.</param>
        public void EditPerfilUsuario(UsuarioInfo usuario, List<ArchivoInfo> listArchivos, string user)
        {
            using (var context = new MIAPDBEntities())
            {
                var miapUsuarioPerfil = (from usuarioPerfil in context.MIAP_USUARIO_PERFIL
                                         where usuarioPerfil.ID_USUARIO == usuario.IdUsuario && usuarioPerfil.ID_PERFIL == usuario.IdPerfil
                                         select usuarioPerfil).Single();

                miapUsuarioPerfil.PUEDE_EJECUTAR_PROYECTO = usuario.PuedeEjecutarProyecto;

                var miapArchivos = (from usuario_Archivo in context.MIAP_USUARIO_ARCHIVO
                                    join archivo in context.MIAP_ARCHIVO
                                    on usuario_Archivo.ID_ARCHIVO equals archivo.ID_ARCHIVO
                                    where (usuario_Archivo.ID_USUARIO == usuario.IdUsuario
                                    && (!usuario.IdProyecto .HasValue || archivo.ID_PROYECTO == usuario.IdProyecto))
                                    select usuario_Archivo).ToList();

                foreach (MIAP_USUARIO_ARCHIVO usuarioArchivo in miapArchivos)
                {
                    context.MIAP_USUARIO_ARCHIVO.Remove(usuarioArchivo);
                }

                MIAP_USUARIO_ARCHIVO miapUsuarioArchivo;

                foreach (ArchivoInfo archivo in listArchivos)
                {
                    miapUsuarioArchivo = new MIAP_USUARIO_ARCHIVO()
                    {
                        ID_USUARIO = usuario.IdUsuario,
                        ID_ARCHIVO = archivo.IdentificadorArchivo,
                        ES_CARGA = archivo.PuedeCargarArchivo,
                        ES_AUTORIZACION = archivo.PuedeAutorizarRecarga,
                        USUARIO_CREACION = user,
                        USUARIO_ACTUALIZACION = user,
                        FECHA_CREACION = DateTime.Now,
                        FECHA_ACTUALIZACION = DateTime.Now,
                    };

                    context.MIAP_USUARIO_ARCHIVO.Add(miapUsuarioArchivo);
                }

                context.SaveChanges();
            }
        }

        /// <summary>
        /// Obtiene los archivos relacionados con el usuario.
        /// </summary>
        /// <param name="idUsuario">Id del usuario del cual se obtendrán los archivos.</param>
        /// <param name="idProyecto">Id del proyecto relacionado a los archivos.</param>        
        /// <returns>Lista con los archivos relacionados con el usuario</returns>
        public List<ArchivoInfo> GetArchivosByUsuario(int idUsuario, int? idProyecto)
        {
            List<ArchivoInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = (from archivoUsuario in context.MIAP_USUARIO_ARCHIVO
                             join archivo in context.MIAP_ARCHIVO
                             on archivoUsuario.ID_ARCHIVO equals archivo.ID_ARCHIVO
                             join proyecto in context.MIAP_PROYECTO
                             on archivo.ID_PROYECTO equals proyecto.ID_PROYECTO
                             where (archivoUsuario.ID_USUARIO == idUsuario
                             && (!idProyecto.HasValue ||  archivo.ID_PROYECTO == idProyecto))
                             select new ArchivoInfo
                             {                                 
                                 NombreArchivo = archivo.NOMBRE,
                                 IdentificadorArchivo = archivoUsuario.ID_ARCHIVO,
                                 PuedeCargarArchivo = archivoUsuario.ES_CARGA,
                                 PuedeAutorizarRecarga = archivoUsuario.ES_AUTORIZACION,

                                 Proyecto = new ProyectoInfo
                                 {
                                     IDProyecto = proyecto.ID_PROYECTO,
                                     NombreProyecto = proyecto.NOMBRE
                                 }
                             }).Distinct().ToList();

                result = query;
            }

            return result;
        }

        /// <summary>
        /// Obtiene la información del perfil del usuario.
        /// </summary>
        /// <param name="idUsuario">Id del usuario del cual se obtendra la infrmación.</param>
        /// <param name="idPerfil">Id del perfil ralacionado al usuario.</param>
        /// <returns>Información del perfil del usuario.</returns>
        public UsuarioInfo GetUsuarioPerfilById(int idUsuario, int idPerfil)
        {
            UsuarioInfo result;

            using (var context = new MIAPDBEntities())
            {
                var query = (from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                             join usuarioPerfil in context.MIAP_USUARIO_PERFIL
                             on usuario.ID_USUARIO equals usuarioPerfil.ID_USUARIO
                             join perfil in context.MIAP_PERFIL
                             on usuarioPerfil.ID_PERFIL equals perfil.ID_PERFIL
                             where usuario.ID_USUARIO == idUsuario && usuarioPerfil.ID_PERFIL == idPerfil
                             select new UsuarioInfo
                             {
                                 IdentificadorPortal = usuario.Clave,
                                 IdUsuario = usuario.ID_USUARIO,
                                 IdProyecto = perfil.ID_PROYECTO,
                                 NombreUsuario = usuario.Nombre,
                                 AliasUsuario = usuario.Usuario,
                                 ApellidoMaterno = usuario.ApellidoMaterno,
                                 ApellidoPaterno = usuario.ApellidoPaterno,
                                 PuedeEjecutarProyecto = usuarioPerfil.PUEDE_EJECUTAR_PROYECTO,
                                 EstaActivo = usuario.Activo,
                                 Area = usuario.Area,
                                 SubArea = usuario.SubArea
                             }).Single();

                result = query;
            }

            return result;
        }

        /// <summary>
        /// Verifica la existencia del perfil para un usuario.
        /// </summary>
        /// <param name="idUsuario">Es el id del usuario.</param>
        /// <param name="idPerfil">Es el id del perfil relacionado con el usuario.</param>
        /// <returns>Indicador.</returns>
        public bool VerifyExistencePerfilUsuario(int idUsuario, int idPerfil)
        {
            using (var context = new MIAPDBEntities())
            {
                var query = (from usuarioPerfil in context.MIAP_USUARIO_PERFIL
                             where usuarioPerfil.ID_USUARIO == idUsuario && usuarioPerfil.ID_PERFIL == idPerfil
                             select usuarioPerfil).FirstOrDefault();

                if (query != null)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        #endregion      
    }
}
